﻿// The Nova Project by Ken Beckett.
// Copyright (C) 2007-2012 Inevitable Software, all rights reserved.
// Released under the Common Development and Distribution License, CDDL-1.0: http://opensource.org/licenses/cddl1.php

using System;
using System.Collections.Generic;
using System.Reflection;

using Nova.CodeDOM;
using Nova.Utilities;

namespace Nova.UI
{
    /// <summary>
    /// The view model for a <see cref="CodeDOM.PropertyRef"/>.
    /// </summary>
    public class PropertyRefVM : VariableRefVM
    {
        #region /* STATICS */

        internal static void AddViewModelMapping()
        {
            CreateViewModel.Add(typeof(PropertyRef),
                delegate(CodeObject codeObject, bool isDescription, Dictionary<CodeObject, CodeObjectVM> dictionary) { return new PropertyRefVM((PropertyRef)codeObject, dictionary); });
        }

        #endregion

        #region /* CONSTRUCTORS */

        /// <summary>
        /// Create a view model instance for the specified <see cref="CodeDOM.PropertyRef"/>.
        /// </summary>
        public PropertyRefVM(PropertyRef propertyRef, Dictionary<CodeObject, CodeObjectVM> dictionary)
            : base(propertyRef, dictionary)
        { }

        #endregion

        #region /* PROPERTIES */

        /// <summary>
        /// The underlying <see cref="CodeDOM.PropertyRef"/> model.
        /// </summary>
        public PropertyRef PropertyRef
        {
            get { return (PropertyRef)CodeObject; }
        }

        #endregion

        #region /* METHODS */

        #endregion

        #region /* RENDERING */

        public static void RenderPropertyInfo(CodeRenderer renderer, PropertyInfo propertyInfo, RenderFlags flags, CodeObjectVM tag)
        {
            RenderFlags passFlags = flags & ~RenderFlags.Description;
            bool hasBorder = flags.HasFlag(RenderFlags.ForceBorder);
            if (hasBorder)
                renderer.CreateBorder(PropertyDeclBaseVM.StaticBorderBrush, PropertyDeclBaseVM.StaticBackgroundBrush, tag);

            if (!flags.HasFlag(RenderFlags.NoPreAnnotations))
                AttributeVM.RenderAttributes(renderer, propertyInfo, tag);
            renderer.RenderText(ModifiersHelpers.AsString(PropertyRef.GetPropertyModifiers(propertyInfo)), KEYWORD_BRUSH, tag);
            Type propertyType = propertyInfo.PropertyType;
            TypeRefBaseVM.RenderTypeAsTypeRefVM(renderer, propertyType, passFlags, tag);  // Render as TypeRefVM for nested tooltips
            renderer.RenderText(" ", PUNC_BRUSH, tag);
            TypeRefBaseVM.RenderTypeAsTypeRefVM(renderer, propertyInfo.DeclaringType, passFlags, tag);  // Render as TypeRefVM for nested tooltips
            DotVM.RenderDot(renderer, tag);

            if (PropertyInfoUtil.IsIndexed(propertyInfo))
            {
                // Display the actual name instead of 'this' - it will usually be 'Item', but not always,
                // plus it might have a prefix (if it's an explicit interface implementation).
                renderer.RenderText(propertyInfo.Name, IDENTIFIER_BRUSH, tag);
                renderer.RenderText(IndexerDecl.ParseTokenStart, PUNC_BRUSH, tag);
                MethodRefVM.RenderParameters(renderer, propertyInfo.GetIndexParameters(), passFlags, tag);
                renderer.RenderText(IndexerDecl.ParseTokenEnd, PUNC_BRUSH, tag);
            }
            else
                renderer.RenderText(propertyInfo.Name, IDENTIFIER_BRUSH, tag);

            // If we have a border, return to the previous one
            if (hasBorder)
                renderer.ReturnToBorderParent(tag);
        }

        #endregion
    }
}
